When you create a COM object for public consumption, you have different options as to how you can make your interface(s) available for public consumption.
If you only want to make your COM object available to low-level programming languages (like C++, C, C#, etc.) which support things like pointers and vtables, you can just create a "custom" interface which inherits from IUnknown.
The problem with this approach is that your COM object will not be available to scripting clients (VBScript, JScript, WScript, etc.), as these clients don't understand pointers and vtables. Instead, you would implement your COM object interface as a derivation of IDispatch. IDispatch provides some methods that allow a scripting client to dynamically discover its methods and properties at runtime instead of compile time. However, this process is less efficient than using IUnknown, as the client has to make extra method calls before calling the desired COM object's method.
So, if you're only targeting low-level programming languages, you could implement your COM interfaces using "custom" interfaces that inherit from IUnknown
If you're only targeting scripting clients, you could implement your interfaces using only IDispatch.
If you want your COM object to be available to scripting languages, and you also want low-level languages to be able to call your methods in a very efficient manner, you should implement both, and this is called "Dual". Probably, Microsoft's examples are all "Dual" because they want their examples to work with both scripting and low-level languages (low-level languages can use IDispatch, but it takes more work).
For more info, I would suggest you watch the .Net Interoperability Course at PluralSight (you can sign up for a free trial subscription). The "COM" part of this course shows you how to create a non-Dual (simple IUnknown interface) as well as "Dual" interfaces.