Our recommendation to developers is that they split their applications across the User Experience/Business Logic fault line. Developers then can replace the user experience with native user interfaces for each platform.
This is a bit abstract, so we tend to tell people to build a lot of UI-less reusable libraries and for libraries that have UIs, to split their Model-View-Controller libraries in a way that the Model and its support infrastructure are reusable and the View and the Controller are UI-specific.
This extends a little bit further. You also might end up with an "OS" layer that performs certain tasks in a different way depending on the operating system that you will be running.
For instance, while running on an iPhone, you have access to the gyroscope, something that you wont find on say a Linux desktop. Or on Linux, you will have access to /proc, which you wont have access to on Windows Mobile 7.
A nice example was Paint.NET. When that application was built, the operating-system specific features were all placed on a library called SystemLayer.dll. The UI was all Windows.Forms, but porting the program turned out to be limited to replacing the SystemLayer.dll with one that spoke Posix as opposed to speaking Win32.
To put it another way, I imagine porting a MonoMac app to Windows would involve a similar level of effort to porting a Windows Forms app to WPF, or vice versa. The more code that lives outside of the presentation layer itself, the easier. To my knowledge, code written for MonoMac will be very Mac-specific (you'll have lots of NS* objects in there), and so it's not a matter of flipping a compiler switch to get a GTK# app or something similar. You'll have to re-write those particular sections.
Again, though, if you architect your project well, you can minimize the amount of re-writing that has to be done.