You can implement your own router and add it to the router cycle in the di configuration.
To add your own router, you have to make the following configuration in the di.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\App\RouterList">
<arguments>
<argument name="routerList" xsi:type="array">
<item name="routername" xsi:type="array">
<item name="class" xsi:type="string">Vendor\Module\Controller\Router</item>
<item name="disable" xsi:type="boolean">false</item>
<item name="sortOrder" xsi:type="string">60</item>
</item>
</argument>
</arguments>
</type>
</config>
Your custom Router class has to implement Magento\Framework\App\RouterInterface
from here, its pretty much up to you to decide when your router catches requests and how they are processed.
Here is also a little devdocs entry on routing: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/routing.html
Basically the routers are called in a cycle in the given sort order multiple times. The routers can modify the Request and at any time a router thinks, he can process the request, it says match = true and processes it.
The cyclecount is internally limited to (i think) a hundred cycles or sth. After that you will land on a 404 page.