Still don't know why NSTextView deallocation is deferred - but it turns out that was a red herring anyway. The reason my undo stack was getting trashed was because I was destroying my NSTextView inside my textDidChange callback (albeit with a retain/autorelease to defer the actual dealloc.)
If I defer my destroyTextView: code by calling it by performSelector:withObject:afterDelay from my textDidChange then all is well (with the undo stack.)
Makes sense now I've found the reason...doesn't it always?