I think you need to live within the 6M limit.
The first thing to do though is to understand what is taking up the space by reviewing your code and thinking about the likely sizes of what you are outputting. (A classic extreme example is querying the body field of Attachments where each body can be up to 5M in size.) You may be able to compromise with what you output e.g. only showing the first 80 characters of strings that could be many thousands of characters long.
Also be aware of Setting Read-Only Mode for an Entire Page thst helps with other limits.
Your intermediate steps my be causing the heap problem. A couple of examples...
Patterns such as this SOQL For Loop:
for (MyType__c t : [select ... from MyType__c ...]) {
...
}
avoids heap space being occupied by all the records queried. Instead the records are queried in batches.
You can also discard intermediate results as soon as they are no longer needed:
List<Something> bigList1 = ...;
List<Something> bigList2 = ...;
List<Something> intermediateResult = ...;
bigList1 = null;
bigList2 = null;
// Heap space for bigList1 and bigList2 now free for other use
because Apex is a garbage collected language where once an object reference is no longer reachable by the code the space occupied by the object can be re-used for other objects.
And also bear in mind that not all problems are suited to a simple Visualforce solution. For example, a more complicated Visualforce page can make multiple JavaScript requests mack to an Apex controller class and so break the problem down into multiple pieces each of which fits within the 6M Apex heap limit.