You can indeed override the serve method and check if the request is a GET or POST. If you don't do all that, the same code is invoked regardless of the request type (unless I'm misremembering). In your serve method, if you detect that the type is a POST, you're responsible for preparing and returning the request object (e.g., JSONResponse or whatever you need to do). Take a look at the source code for the Page object, it is pretty clear and will help you understand the page lifecycle better.
I generally try to avoid overriding the serve method to handle different types of requests though. For non-Ajax, my preferred pattern for this sort of thing is to POST to a url that is outside of the CMS, handling it with Plain Old Django (nothing Wagtail specific) and then redirect back to the page to display confirmation/errors/etc. Usually I handle all form submissions as Ajax though, and for this I use Django Rest Framework (now an optional dependency I believe?), even for simple stuff like contact forms.