You don't have to be using NSUserDefaultsController to use KVO, you just have to make sure to use the get/set convention in your method names, and as long as you inherit from NSObject everything should be setup fine to use KVO.
Once I understood what was required, this was pretty easy to implement. To save you some trouble if you've found this thread while searching for help doing the same thing:
In my main controller, I added the following line to awakeFromNib:
So, when the code hits the "postNotificationName" line, it drops a message named "PreferencesChanged" into the Notification dispatch table. The observer (in the main controller) is primed to look for any notifications named "PreferencesChanged", and when one is found, it redirects processing to the preferencesChanged method.